home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / lisp / wgdb-42.lha / wgdb-4.2 / gdb / cplus-dem.c < prev    next >
C/C++ Source or Header  |  1992-09-11  |  21KB  |  1,043 lines

  1. /* Demangler for GNU C++ 
  2.    Copyright (C) 1989 Free Software Foundation, Inc.
  3.    written by James Clark (jjc@jclark.uucp)
  4.    
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9.  
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. /* This is for g++ 1.36.1 (November 6 version). It will probably
  20.    require changes for any other version.
  21.  
  22.    Modified for g++ 1.36.2 (November 18 version).
  23.  
  24.    Modified for g++ 1.90.06 (December 31 version).  */
  25.  
  26. /* This file exports one function
  27.  
  28.    char *cplus_demangle (const char *name, int mode)
  29.    
  30.    If NAME is a mangled function name produced by GNU C++, then
  31.    a pointer to a malloced string giving a C++ representation
  32.    of the name will be returned; otherwise NULL will be returned.
  33.    It is the caller's responsibility to free the string which
  34.    is returned.
  35.  
  36.    If MODE > 0, then ANSI qualifiers such as `const' and `void' are output.
  37.    Otherwise they are not.
  38.    If MODE >= 0, parameters are emitted; otherwise not.
  39.  
  40.    For example,
  41.    
  42.    cplus_demangle ("foo__1Ai",  0)    => "A::foo(int)"
  43.    cplus_demangle ("foo__1Ai",  1)    => "A::foo(int)"
  44.    cplus_demangle ("foo__1Ai", -1)    => "A::foo"
  45.  
  46.    cplus_demangle ("foo__1Afe",  0)    => "A::foo(float,...)"
  47.    cplus_demangle ("foo__1Afe",  1)    => "A::foo(float,...)"
  48.    cplus_demangle ("foo__1Afe", -1)    => "A::foo"
  49.  
  50.    This file imports xmalloc and xrealloc, which are like malloc and
  51.    realloc except that they generate a fatal error if there is no
  52.    available memory. */
  53.  
  54. /* define this if names don't start with _ */
  55. /* #define nounderscore 1 */
  56.  
  57. #include <stdio.h>
  58. #include <ctype.h>
  59.  
  60. /* GDB-specific, FIXME.  */
  61. #include "defs.h"
  62. #include "param.h"
  63.  
  64. #ifdef USG
  65. #include <memory.h>
  66. #include <string.h>
  67. #else
  68. #include <strings.h>
  69. #define memcpy(s1, s2, n) bcopy ((s2), (s1), (n))
  70. #define memcmp(s1, s2, n) bcmp ((s2), (s1), (n))
  71. #define strchr index 
  72. #define strrchr rindex
  73. #endif
  74.  
  75. /* This is '$' on systems where the assembler can deal with that.
  76.    Where the assembler can't, it's '.' (but on many systems '.' is
  77.    used for other things).  */
  78. #if !defined (CPLUS_MARKER)
  79. #define CPLUS_MARKER '$'
  80. #endif
  81.  
  82. #ifndef __STDC__
  83. #define const
  84. #endif
  85.  
  86. #ifdef __STDC__
  87. extern char *cplus_demangle (const char *type, int mode);
  88. #else
  89. extern char *cplus_demangle ();
  90. #endif
  91.  
  92. #ifdef __STDC__
  93. /* GDB prototypes these as void* in defs.h, so we better too, at least
  94.    as long as we're including defs.h.  */
  95. extern void *xmalloc (int);
  96. extern void *xrealloc (char *, int);
  97. extern void free (void *);
  98. #else
  99. extern char *xmalloc ();
  100. extern char *xrealloc ();
  101. extern void free ();
  102. #endif
  103.  
  104. static char **typevec = 0;
  105. static int ntypes = 0;
  106. static int typevec_size = 0;
  107.  
  108. const static struct optable {
  109.   const char *in;
  110.   const char *out;
  111. } optable[] = {
  112.   "nw", " new",            /* new (1.92) */
  113.   "dl", " delete",        /* new (1.92) */
  114.   "new", " new",        /* old (1.91, and 1.x) */
  115.   "delete", " delete",        /* old (1.91, and 1.x) */
  116.   "ne", "!=",
  117.   "eq", "==",
  118.   "ge", ">=",
  119.   "gt", ">",
  120.   "le", "<=",
  121.   "lt", "<",
  122.   "plus", "+",
  123.   "minus", "-",
  124.   "mult", "*",
  125.   "convert", "+",    /* unary + */
  126.   "negate", "-",    /* unary - */
  127.   "trunc_mod", "%",
  128.   "trunc_div", "/",
  129.   "truth_andif", "&&",
  130.   "truth_orif", "||",
  131.   "truth_not", "!",
  132.   "postincrement", "++",
  133.   "postdecrement", "--",
  134.   "bit_ior", "|",
  135.   "bit_xor", "^",
  136.   "bit_and", "&",
  137.   "bit_not", "~",
  138.   "call", "()",
  139.   "cond", "?:",
  140.   "alshift", "<<",
  141.   "arshift", ">>",
  142.   "component", "->",
  143.   "indirect", "*",
  144.   "method_call", "->()",
  145.   "addr", "&",        /* unary & */
  146.   "array", "[]",
  147.   "compound", ",",
  148.   "nop", "",            /* for operator= */
  149. };
  150.  
  151. /* Beware: these aren't '\0' terminated. */
  152.  
  153. typedef struct string {
  154.   char *b;            /* pointer to start of string */
  155.   char *p;            /* pointer after last character */
  156.   char *e;            /* pointer after end of allocated space */
  157. } string;
  158.  
  159. #ifdef __STDC__
  160. static void string_need (string *s, int n);
  161. static void string_delete (string *s);
  162. static void string_init (string *s);
  163. static void string_clear (string *s);
  164. static int string_empty (string *s);
  165. static void string_append (string *p, const char *s);
  166. static void string_appends (string *p, string *s);
  167. static void string_appendn (string *p, const char *s, int n);
  168. static void string_prepend (string *p, const char *s);
  169. #if 0
  170. static void string_prepends (string *p, string *s);
  171. #endif
  172. static void string_prependn (string *p, const char *s, int n);
  173. static int get_count (const char **type, int *count);
  174. static int do_args (const char **type, string *decl, int arg_mode);
  175. static int do_type (const char **type, string *result, int arg_mode);
  176. static int do_arg (const char **type, string *result, int arg_mode);
  177. static void munge_function_name (string *name, int arg_mode);
  178. static void remember_type (const char *type, int len);
  179. #else
  180. static void string_need ();
  181. static void string_delete ();
  182. static void string_init ();
  183. static void string_clear ();
  184. static int string_empty ();
  185. static void string_append ();
  186. static void string_appends ();
  187. static void string_appendn ();
  188. static void string_prepend ();
  189. #if 0
  190. static void string_prepends ();
  191. #endif
  192. static void string_prependn ();
  193. static int get_count ();
  194. static int do_args ();
  195. static int do_type ();
  196. static int do_arg ();
  197. static int do_args ();
  198. static void munge_function_name ();
  199. static void remember_type ();
  200. #endif
  201.  
  202. /* Takes operator name as e.g. "++" and returns mangled
  203.    operator name (e.g. "postincrement_expr"), or NULL if not found.  */
  204. char *
  205. cplus_mangle_opname (opname)
  206.      char *opname;
  207. {
  208.   int i, len = strlen (opname);
  209.  
  210.   for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
  211.     {
  212.       if (strlen (optable[i].out) == len
  213.       && memcmp (optable[i].out, opname, len) == 0)
  214.     return (char *)optable[i].in;
  215.     }
  216.   return 0;
  217. }
  218.  
  219. char *
  220. cplus_demangle (type, arg_mode)
  221.      const char *type;
  222.      int arg_mode;
  223. {
  224.   string decl;
  225.   int n;
  226.   int success = 0;
  227.   int constructor = 0;
  228.   int const_flag = 0;
  229.   int i;
  230.   const char *p;
  231. #ifndef LONGERNAMES
  232.   const char *premangle;
  233. #endif
  234.  
  235. # define print_ansi_qualifiers (arg_mode >  0)
  236. # define print_arg_types       (arg_mode >= 0)
  237.  
  238.   if (type == NULL || *type == '\0')
  239.     return NULL;
  240. #ifndef nounderscore
  241.   if (*type++ != '_')
  242.     return NULL;
  243. #endif
  244.   p = type;
  245.   while (*p != '\0' && !(*p == '_' && p[1] == '_'))
  246.     p++;
  247.   if (*p == '\0')
  248.     {
  249.       /* destructor */
  250.       if (type[0] == '_' && type[1] == CPLUS_MARKER && type[2] == '_')
  251.     {
  252.       char *tem = (char *) xmalloc ((strlen (type) - 3)*2 + 3 + 2 + 1);
  253.       strcpy (tem, type + 3);
  254.       strcat (tem, "::~");
  255.       strcat (tem, type + 3);
  256.       strcat (tem, "()");
  257.       return tem;
  258.     }
  259.       /* static data member */
  260.       if (*type != '_' && (p = strchr (type, CPLUS_MARKER)) != NULL)
  261.     {
  262.       char *tem = (char *) xmalloc (strlen (type) + 2);
  263.       memcpy (tem, type, p - type);
  264.       strcpy (tem + (p - type), "::");
  265.       strcpy (tem + (p - type) + 2, p + 1);
  266.       return tem;
  267.     }
  268.       /* virtual table "_vt$" */
  269.       if (type[0] == '_' && type[1] == 'v' && type[2] == 't' && type[3] == CPLUS_MARKER)
  270.     {
  271.       char *tem = (char *) xmalloc (strlen (type + 4) + 14 + 1);
  272.       strcpy (tem, type + 4);
  273.       strcat (tem, " virtual table");
  274.       return tem;
  275.     }
  276.       return NULL;
  277.     }
  278.  
  279.   string_init (&decl);
  280.  
  281.   if (p == type)
  282.     {
  283.       if (!isdigit (p[2]))
  284.     {
  285.       string_delete (&decl);
  286.       return NULL;
  287.     }
  288.       constructor = 1;
  289.     }
  290.   else
  291.     {
  292.       string_appendn (&decl, type, p - type);
  293.       munge_function_name (&decl, arg_mode);
  294.     }
  295.   p += 2;
  296.  
  297. #ifndef LONGERNAMES
  298.   premangle = p;
  299. #endif
  300.   switch (*p)
  301.     {
  302.     case 'C':
  303.       /* a const member function */
  304.       if (!isdigit (p[1]))
  305.     {
  306.       string_delete (&decl);
  307.       return NULL;
  308.     }
  309.       p += 1;
  310.       const_flag = 1;
  311.       /* fall through */
  312.     case '0':
  313.     case '1':
  314.     case '2':
  315.     case '3':
  316.     case '4':
  317.     case '5':
  318.     case '6':
  319.     case '7':
  320.     case '8':
  321.     case '9':
  322.       n = 0;
  323.       do
  324.     {
  325.       n *= 10;
  326.       n += *p - '0';
  327.       p += 1;
  328.     }
  329.       while (isdigit (*p));
  330.       if (strlen (p) < n)
  331.     {
  332.       string_delete (&decl);
  333.       return NULL;
  334.     }
  335.       if (constructor)
  336.     {
  337.       string_appendn (&decl, p, n);
  338.       string_append (&decl, "::");
  339.       string_appendn (&decl, p, n);
  340.     }
  341.       else
  342.     {
  343.       string_prepend (&decl, "::");
  344.       string_prependn (&decl, p, n);
  345.     }
  346.       p += n;
  347. #ifndef LONGERNAMES
  348.       remember_type (premangle, p - premangle);
  349. #endif
  350.       success = do_args (&p, &decl, arg_mode);
  351.       if (const_flag && print_arg_types)
  352.     string_append (&decl, " const");
  353.       break;
  354.     case 'F':
  355.       p += 1;
  356.       success = do_args (&p, &decl, arg_mode);
  357.       break;
  358.     }
  359.  
  360.   for (i = 0; i < ntypes; i++)
  361.     if (typevec[i] != NULL)
  362.       free (typevec[i]);
  363.   ntypes = 0;
  364.   if (typevec != NULL)
  365.     {
  366.       free ((char *)typevec);
  367.       typevec = NULL;
  368.       typevec_size = 0;
  369.     }
  370.  
  371.   if (success)
  372.     {
  373.       string_appendn (&decl, "", 1);
  374.       return decl.b;
  375.     }
  376.   else
  377.     {
  378.       string_delete (&decl);
  379.       return NULL;
  380.     }
  381. }
  382.  
  383. static int
  384. get_count (type, count)
  385.      const char **type;
  386.      int *count;
  387. {
  388.   if (!isdigit (**type))
  389.     return 0;
  390.   *count = **type - '0';
  391.   *type += 1;
  392.   /* see flush_repeats in cplus-method.c */
  393.   if (isdigit (**type))
  394.     {
  395.       const char *p = *type;
  396.       int n = *count;
  397.       do 
  398.     {
  399.       n *= 10;
  400.       n += *p - '0';
  401.       p += 1;
  402.     } 
  403.       while (isdigit (*p));
  404.       if (*p == '_')
  405.     {
  406.       *type = p + 1;
  407.       *count = n;
  408.     }
  409.     }
  410.   return 1;
  411. }
  412.  
  413. /* result will be initialised here; it will be freed on failure */
  414.  
  415. static int
  416. do_type (type, result, arg_mode)
  417.      const char **type;
  418.      string *result;
  419.      int arg_mode;
  420. {
  421.   int n;
  422.   int done;
  423.   int non_empty = 0;
  424.   int success;
  425.   string decl;
  426.   const char *remembered_type;
  427.  
  428.   string_init (&decl);
  429.   string_init (result);
  430.  
  431.   done = 0;
  432.   success = 1;
  433.   while (success && !done)
  434.     {
  435.       int member;
  436.       switch (**type)
  437.     {
  438.     case 'Q':
  439.       n = (*type)[1] - '0';
  440.       if (n < 0 || n > 9)
  441.         success = 0;
  442.       *type += 2;
  443.       while (n-- > 0)
  444.         do_type (type, result, arg_mode);
  445.       break;
  446.  
  447.     case 'P':
  448.       *type += 1;
  449.       string_prepend (&decl, "*");
  450.       break;
  451.  
  452.     case 'R':
  453.       *type += 1;
  454.       string_prepend (&decl, "&");
  455.       break;
  456.  
  457.     case 'T':
  458.       *type += 1;
  459.       if (!get_count (type, &n) || n >= ntypes)
  460.         success = 0;
  461.       else
  462.         {
  463.           remembered_type = typevec[n];
  464.           type = &remembered_type;
  465.         }
  466.       break;
  467.  
  468.     case 'F':
  469.       *type += 1;
  470.       if (!string_empty (&decl) && decl.b[0] == '*')
  471.         {
  472.           string_prepend (&decl, "(");
  473.           string_append (&decl, ")");
  474.         }
  475.       if (!do_args (type, &decl, arg_mode) || **type != '_')
  476.         success = 0;
  477.       else
  478.         *type += 1;
  479.       break;
  480.  
  481.     case 'M':
  482.     case 'O':
  483.       {
  484.         int constp = 0;
  485.         int volatilep = 0;
  486.  
  487.         member = **type == 'M';
  488.         *type += 1;
  489.         if (!isdigit (**type))
  490.           {
  491.         success = 0;
  492.         break;
  493.           }
  494.         n = 0;
  495.         do
  496.           {
  497.         n *= 10;
  498.         n += **type - '0';
  499.         *type += 1;
  500.           } 
  501.         while (isdigit (**type));
  502.         if (strlen (*type) < n)
  503.           {
  504.         success = 0;
  505.         break;
  506.           }
  507.         string_append (&decl, ")");
  508.         string_prepend (&decl, "::");
  509.         string_prependn (&decl, *type, n);
  510.         string_prepend (&decl, "(");
  511.         *type += n;
  512.         if (member)
  513.           {
  514.         if (**type == 'C')
  515.           {
  516.             *type += 1;
  517.             constp = 1;
  518.           }
  519.         if (**type == 'V')
  520.           {
  521.             *type += 1;
  522.             volatilep = 1;
  523.           }
  524.         if (*(*type)++ != 'F')
  525.           {
  526.             success = 0;
  527.             break;
  528.           }
  529.           }
  530.         if ((member && !do_args (type, &decl, arg_mode)) || **type != '_')
  531.           {
  532.         success = 0;
  533.         break;
  534.           }
  535.         *type += 1;
  536.         if (! print_ansi_qualifiers)
  537.           break;
  538.         if (constp)
  539.           {
  540.         if (non_empty)
  541.           string_append (&decl, " ");
  542.         else
  543.           non_empty = 1;
  544.         string_append (&decl, "const");
  545.           }
  546.         if (volatilep)
  547.           {
  548.         if (non_empty)
  549.           string_append (&decl, " ");
  550.         else
  551.           non_empty = 1;
  552.         string_append (&decl, "volatile");
  553.           }
  554.         break;
  555.       }
  556.  
  557.     case 'C':
  558.       if ((*type)[1] == 'P')
  559.         {
  560.           *type += 1;
  561.           if (print_ansi_qualifiers)
  562.         {
  563.           if (!string_empty (&decl))
  564.             string_prepend (&decl, " ");
  565.           string_prepend (&decl, "const");
  566.         }
  567.           break;
  568.         }
  569.  
  570.       /* fall through */
  571.     default:
  572.       done = 1;
  573.       break;
  574.     }
  575.     }
  576.  
  577.   done = 0;
  578.   non_empty = 0;
  579.   while (success && !done)
  580.     {
  581.       switch (**type)
  582.     {
  583.     case 'C':
  584.       *type += 1;
  585.       if (print_ansi_qualifiers)
  586.         {
  587.           if (non_empty)
  588.         string_append (result, " ");
  589.           else
  590.         non_empty = 1;
  591.           string_append (result, "const");
  592.         }
  593.       break;
  594.     case 'U':
  595.       *type += 1;
  596.       if (non_empty)
  597.         string_append (result, " ");
  598.       else
  599.         non_empty = 1;
  600.       string_append (result, "unsigned");
  601.       break;
  602.     case 'V':
  603.       *type += 1;
  604.       if (print_ansi_qualifiers)
  605.         {
  606.           if (non_empty)
  607.         string_append (result, " ");
  608.           else
  609.         non_empty = 1;
  610.           string_append (result, "volatile");
  611.         }
  612.       break;
  613.     default:
  614.       done = 1;
  615.       break;
  616.     }
  617.     }
  618.  
  619.   if (success)
  620.     switch (**type)
  621.       {
  622.       case '\0':
  623.       case '_':
  624.     break;
  625.       case 'v':
  626.     *type += 1;
  627.     if (non_empty)
  628.       string_append (result, " ");
  629.     string_append (result, "void");
  630.     break;
  631.       case 'x':
  632.     *type += 1;
  633.     if (non_empty)
  634.       string_append (result, " ");
  635.     string_append (result, "long long");
  636.     break;
  637.       case 'l':
  638.     *type += 1;
  639.     if (non_empty)
  640.       string_append (result, " ");
  641.     string_append (result, "long");
  642.     break;
  643.       case 'i':
  644.     *type += 1;
  645.     if (non_empty)
  646.       string_append (result, " ");
  647.     string_append (result, "int");
  648.     break;
  649.       case 's':
  650.     *type += 1;
  651.     if (non_empty)
  652.       string_append (result, " ");
  653.     string_append (result, "short");
  654.     break;
  655.       case 'c':
  656.     *type += 1;
  657.     if (non_empty)
  658.       string_append (result, " ");
  659.     string_append (result, "char");
  660.     break;
  661.       case 'r':
  662.     *type += 1;
  663.     if (non_empty)
  664.       string_append (result, " ");
  665.     string_append (result, "long double");
  666.     break;
  667.       case 'd':
  668.     *type += 1;
  669.     if (non_empty)
  670.       string_append (result, " ");
  671.     string_append (result, "double");
  672.     break;
  673.       case 'f':
  674.     *type += 1;
  675.     if (non_empty)
  676.       string_append (result, " ");
  677.     string_append (result, "float");
  678.     break;
  679.       case 'G':
  680.     *type += 1;
  681.     if (!isdigit (**type))
  682.       {
  683.         success = 0;
  684.         break;
  685.       }
  686.     /* fall through */
  687.       case '0':
  688.       case '1':
  689.       case '2':
  690.       case '3':
  691.       case '4':
  692.       case '5':
  693.       case '6':
  694.       case '7':
  695.       case '8':
  696.       case '9':
  697.     n = 0;
  698.     do
  699.       {
  700.         n *= 10;
  701.         n += **type - '0';
  702.         *type += 1;
  703.       }
  704.     while (isdigit (**type));
  705.     if (strlen (*type) < n)
  706.       {
  707.         success = 0;
  708.         break;
  709.       }
  710.     if (non_empty)
  711.       string_append (result, " ");
  712.     string_appendn (result, *type, n);
  713.     *type += n;
  714.     break;
  715.       default:
  716.     success = 0;
  717.     break;
  718.       }
  719.  
  720.   if (success)
  721.     {
  722.       if (!string_empty (&decl))
  723.     {
  724.       string_append (result, " ");
  725.       string_appends (result, &decl);
  726.     }
  727.       string_delete (&decl);
  728.       return 1;
  729.     }
  730.   else
  731.     {
  732.       string_delete (&decl);
  733.       string_delete (result);
  734.       return 0;
  735.     }
  736. }
  737.  
  738. /* `result' will be initialised in do_type; it will be freed on failure */
  739.  
  740. static int
  741. do_arg (type, result, arg_mode)
  742.      const char **type;
  743.      string *result;
  744.      int arg_mode;
  745. {
  746.   const char *start = *type;
  747.  
  748.   if (!do_type (type, result, arg_mode))
  749.     return 0;
  750.   remember_type (start, *type - start);
  751.   return 1;
  752. }
  753.  
  754. static void
  755. remember_type (start, len)
  756.      const char *start;
  757.      int len;
  758. {
  759.   char *tem;
  760.  
  761.   if (ntypes >= typevec_size)
  762.     {
  763.       if (typevec_size == 0)
  764.     {
  765.       typevec_size = 3;
  766.       typevec = (char **) xmalloc (sizeof (char*)*typevec_size);
  767.     }
  768.       else
  769.     {
  770.       typevec_size *= 2;
  771.       typevec = (char **) xrealloc ((char *)typevec, sizeof (char*)*typevec_size);
  772.     }
  773.     }
  774.   tem = (char *) xmalloc (len + 1);
  775.   memcpy (tem, start, len);
  776.   tem[len] = '\0';
  777.   typevec[ntypes++] = tem;
  778. }
  779.  
  780. /* `decl' must be already initialised, usually non-empty;
  781.    it won't be freed on failure */
  782.  
  783. static int
  784. do_args (type, decl, arg_mode)
  785.      const char **type;
  786.      string *decl;
  787.      int arg_mode;
  788. {
  789.   string arg;
  790.   int need_comma = 0;
  791.  
  792.   if (print_arg_types)
  793.     string_append (decl, "(");
  794.  
  795.   while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v')
  796.     {
  797.       if (**type == 'N')
  798.     {
  799.       int r;
  800.       int t;
  801.       *type += 1;
  802.       if (!get_count (type, &r) || !get_count (type, &t) || t >= ntypes)
  803.         return 0;
  804.       while (--r >= 0)
  805.         {
  806.           const char *tem = typevec[t];
  807.           if (need_comma && print_arg_types)
  808.         string_append (decl, ", ");
  809.           if (!do_arg (&tem, &arg, arg_mode))
  810.         return 0;
  811.           if (print_arg_types)
  812.         string_appends (decl, &arg);
  813.           string_delete (&arg);
  814.           need_comma = 1;
  815.         }
  816.     }
  817.       else
  818.     {
  819.       if (need_comma & print_arg_types)
  820.         string_append (decl, ", ");
  821.       if (!do_arg (type, &arg, arg_mode))
  822.         return 0;
  823.       if (print_arg_types)
  824.         string_appends (decl, &arg);
  825.       string_delete (&arg);
  826.       need_comma = 1;
  827.     }
  828.     }
  829.  
  830.   if (**type == 'v')
  831.     *type += 1;
  832.   else if (**type == 'e')
  833.     {
  834.       *type += 1;
  835.       if (print_arg_types)
  836.     {
  837.       if (need_comma)
  838.         string_append (decl, ",");
  839.       string_append (decl, "...");
  840.     }
  841.     }
  842.  
  843.   if (print_arg_types)
  844.     string_append (decl, ")");
  845.   return 1;
  846. }
  847.  
  848. static void
  849. munge_function_name (name, arg_mode)
  850.      string *name;
  851.      int arg_mode;
  852. {
  853.   if (!string_empty (name) && name->p - name->b >= 3 
  854.       && name->b[0] == 'o' && name->b[1] == 'p' && name->b[2] == CPLUS_MARKER)
  855.     {
  856.       int i;
  857.       /* see if it's an assignment expression */
  858.       if (name->p - name->b >= 10 /* op$assign_ */
  859.       && memcmp (name->b + 3, "assign_", 7) == 0)
  860.     {
  861.       for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
  862.         {
  863.           int len = name->p - name->b - 10;
  864.           if (strlen (optable[i].in) == len
  865.           && memcmp (optable[i].in, name->b + 10, len) == 0)
  866.         {
  867.           string_clear (name);
  868.           string_append (name, "operator");
  869.           string_append (name, optable[i].out);
  870.           string_append (name, "=");
  871.           return;
  872.         }
  873.         }
  874.     }
  875.       else
  876.     {
  877.       for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
  878.         {
  879.           int len = name->p - name->b - 3;
  880.           if (strlen (optable[i].in) == len 
  881.           && memcmp (optable[i].in, name->b + 3, len) == 0)
  882.         {
  883.           string_clear (name);
  884.           string_append (name, "operator");
  885.           string_append (name, optable[i].out);
  886.           return;
  887.         }
  888.         }
  889.     }
  890.       return;
  891.     }
  892.   else if (!string_empty (name) && name->p - name->b >= 5
  893.        && memcmp (name->b, "type$", 5) == 0)
  894.     {
  895.       /* type conversion operator */
  896.       string type;
  897.       const char *tem = name->b + 5;
  898.       if (do_type (&tem, &type, arg_mode))
  899.     {
  900.       string_clear (name);
  901.       string_append (name, "operator ");
  902.       string_appends (name, &type);
  903.       string_delete (&type);
  904.       return;
  905.     }
  906.     }
  907. }
  908.  
  909. /* a mini string-handling package */
  910.  
  911. static void
  912. string_need (s, n)
  913.      string *s;
  914.      int n;
  915. {
  916.   if (s->b == NULL)
  917.     {
  918.       if (n < 32)
  919.     n = 32;
  920.       s->p = s->b = (char *) xmalloc (n);
  921.       s->e = s->b + n;
  922.     }
  923.   else if (s->e - s->p < n)
  924.     {
  925.       int tem = s->p - s->b;
  926.       n += tem;
  927.       n *= 2;
  928.       s->b = (char *) xrealloc (s->b, n);
  929.       s->p = s->b + tem;
  930.       s->e = s->b + n;
  931.     }
  932. }
  933.  
  934. static void
  935. string_delete (s)
  936.      string *s;
  937. {
  938.   if (s->b != NULL)
  939.     {
  940.       free (s->b);
  941.       s->b = s->e = s->p = NULL;
  942.     }
  943. }
  944.  
  945. static void
  946. string_init (s)
  947.      string *s;
  948. {
  949.   s->b = s->p = s->e = NULL;
  950. }
  951.  
  952. static void 
  953. string_clear (s)
  954.      string *s;
  955. {
  956.   s->p = s->b;
  957. }
  958.  
  959. static int
  960. string_empty (s)
  961.      string *s;
  962. {
  963.   return s->b == s->p;
  964. }
  965.  
  966. static void
  967. string_append (p, s)
  968.      string *p;
  969.      const char *s;
  970. {
  971.   int n;
  972.   if (s == NULL || *s == '\0')
  973.     return;
  974.   n = strlen (s);
  975.   string_need (p, n);
  976.   memcpy (p->p, s, n);
  977.   p->p += n;
  978. }
  979.  
  980. static void
  981. string_appends (p, s)
  982.      string *p, *s;
  983. {
  984.   int n;
  985.   if (s->b == s->p)
  986.     return;
  987.   n = s->p - s->b;
  988.   string_need (p, n);
  989.   memcpy (p->p, s->b, n);
  990.   p->p += n;
  991. }
  992.  
  993. static void
  994. string_appendn (p, s, n)
  995.      string *p;
  996.      const char *s;
  997.      int n;
  998. {
  999.   if (n == 0)
  1000.     return;
  1001.   string_need (p, n);
  1002.   memcpy (p->p, s, n);
  1003.   p->p += n;
  1004. }
  1005.  
  1006. static void
  1007. string_prepend (p, s)
  1008.      string *p;
  1009.      const char *s;
  1010. {
  1011.   if (s == NULL || *s == '\0')
  1012.     return;
  1013.   string_prependn (p, s, strlen (s));
  1014. }
  1015.  
  1016. #if 0
  1017. static void
  1018. string_prepends (p, s)
  1019.      string *p, *s;
  1020. {
  1021.   if (s->b == s->p)
  1022.     return;
  1023.   string_prependn (p, s->b, s->p - s->b);
  1024. }
  1025. #endif
  1026.  
  1027. static void
  1028. string_prependn (p, s, n)
  1029.      string *p;
  1030.      const char *s;
  1031.      int n;
  1032. {
  1033.   char *q;
  1034.  
  1035.   if (n == 0)
  1036.     return;
  1037.   string_need (p, n);
  1038.   for (q = p->p - 1; q >= p->b; q--)
  1039.     q[n] = q[0];
  1040.   memcpy (p->b, s, n);
  1041.   p->p += n;
  1042. }
  1043.